using System;

namespace ArithemeticSolver
{
	internal class Operator : Element
	{
		private readonly OperatorType m_operatorType;
		private readonly int m_priority;

		public Operator(string operatorString)
		{
			m_operatorType = ToOperatorType(operatorString);
			m_priority = GetPriority();
		}

		private int GetPriority()
		{
			switch(m_operatorType)
			{
				case OperatorType.Add:
				case OperatorType.Sub:
					return 0;

				case OperatorType.Mul:
				case OperatorType.Div:
					return 1;
			}

			throw new ApplicationException();
		}

		public IValue Evaluate(IValue left, IValue right)
		{
			var value = EvaluateValue(left.Value, right.Value);
			return new Operand(value);
		}

		private float EvaluateValue(float left, float right)
		{
			switch(m_operatorType)
			{
				case OperatorType.Add:
					return left + right;

				case OperatorType.Sub:
					return left - right;

				case OperatorType.Mul:
					return left*right;

				case OperatorType.Div:
					return left/right;
			}
			throw new ApplicationException();
		}

		public bool IsSameOrHigherPriorityThan(Operator op)
		{
			if (op == null) return true;
			return m_priority >= op.m_priority;
		}

		#region Helper
		private enum OperatorType
		{
			Add,
			Sub,
			Mul,
			Div
		}

		private static OperatorType ToOperatorType(string operatorString)
		{
			switch (operatorString)
			{
				case "+":
					return OperatorType.Add;
				case "-":
					return OperatorType.Sub;
				case "*":
					return OperatorType.Mul;
				case "/":
					return OperatorType.Div;
			}
			throw new ArgumentException("Invalid Operator String : " + operatorString);
		}
		#endregion
	}
}